import React, { useState } from 'react'
import { Button } from 'antd';
import { flushSync } from 'react-dom';

// useState简单原理
let _state
const useStateSelf = (initialValue)=> {
    if (typeof _state === 'undefined') {
        if (typeof initialValue === 'function') {
            _state = initialValue()
        } else {
            _state = initialValue
        }
    }

    const setState = (value) =>{
        // 比较_state和value是否相等
        /**
        * NaN === NaN 的结果是 false，因为 NaN 不与自身相等。但 Object.is(NaN, NaN) 的结果是 true。
        * +0 === -0 的结果是 true，因为它们在数值上相等。然而 Object.is(+0, -0) 的结果是 false。
        **/
        //    相等直接返回
        if (Object.is(value, _state)) return
        //   不相等则赋值
        if (typeof value === "function") {
            _state = value(_state)
        } else {
            _state = value
        }
        // 通知视图更新 
    }

    return [_state, setState]

}

// 需求：让函数只更新一次，但是最后的结果是20
// setX的时候不直接传入值，而是用箭头函数。原理是闭包
const Demo = function Demo() {
    console.log('RENDER渲染');
    let [x, setX] = useState(10);
    // let [x, setX] = useStateSelf(10);

    const handle = () => {
        for (let i = 0; i < 10; i++) {
            // setX(x + 1)
            // console.log(x);
            flushSync()
            setX(prev => {
                // prev:存储上一次的状态值
                console.log(prev);
                return prev + 1; //返回的信息是我们要修改的状态值
            });
        }
    };
    return <div className="demo">
        <span className="num">x:{x}</span>
        <Button type="primary"
            size="small"
            onClick={handle}>
            新增
        </Button>
    </div>;
};

export default function DemoState(props) {
    // console.log('props',props);
    // 我们需要把基于属性传递进来的x/y，经过其他处理的结果作为初始值
    // 此时我们需要对初始值的操作，进行惰性化处理：只有第一次渲染组件处理这些逻辑，以后组件更新，这样的逻辑就不要再运行了！！
    let [num, setNum] = useState(() => {
        let { x, y } = props,
            total = 0;
        for (let i = x; i <= y; i++) {
            total += +String(Math.random()).substring(2);
        }
        return total;
    });

    const handle = () => {
        setNum(1000);
    };
    return <>
        <Demo />
        <div className="demo">
            <span className="num">{num}</span>
            <Button type="primary"
                size="small"
                onClick={handle}>
                新增
            </Button>
        </div></>;
};